#include "statement.h"
#include "recordset.h"

CStatementImpl::CStatementImpl(sqlite3* pSqlite3) : m_pSqlite3(pSqlite3)
{
}

CStatementImpl::~CStatementImpl(void)
{
}

HRESULT CStatementImpl::Query(LPCSTR lpszSQL, UINT ulen, IRecordSet** pRecordSet)
{
    StmtPtr pStmt3 = compile(m_pSqlite3, lpszSQL);
    rc_error(pStmt3.m_p != NULL, E_FAIL);
    return CRecordSet::CreateInstance(pStmt3, pRecordSet);
}

int CStatementImpl::Execute(LPCSTR lpszSQL, UINT ulen)
{
    char* pszErrorMsg = NULL;

    StmtPtr pStmt3 = compile(m_pSqlite3, lpszSQL);
    int rc = sqlite3_step(pStmt3);
    rc_error(rc == SQLITE_DONE, S_ERROR);
    rc = sqlite3_changes(m_pSqlite3);
    return rc;
}

int CStatementImpl::Insert(LPCSTR lpszSQL, UINT ulen)
{
    char* pszErrorMsg = NULL;
    m_pStmt = compile(m_pSqlite3, lpszSQL);
    rc_error(m_pStmt.m_p != NULL, E_FAIL);

    m_nParamCount = sqlite3_bind_parameter_count(m_pStmt);

    return m_nParamCount;
}

HRESULT CStatementImpl::SetInt(unsigned int nIndex, INT nValue)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = sqlite3_bind_int(m_pStmt, nIndex, nValue);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetUInt(unsigned int nIndex, UINT nValue)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = SetInt64(nIndex, nValue);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetInt64(unsigned int nIndex, int64 nValue)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = sqlite3_bind_int64(m_pStmt, nIndex, nValue);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetDouble(unsigned int nIndex, double dbValue)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = sqlite3_bind_double(m_pStmt, nIndex, dbValue);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetFloat(unsigned int nIndex, float fValue)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = SetDouble(nIndex, fValue);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT
CStatementImpl::SetBlob(unsigned int nIndex, const unsigned char* lpszData, int nSize)
{
    rc_error(lpszData != NULL, E_INVALIDARG);
    ;
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = sqlite3_bind_blob(m_pStmt, nIndex, lpszData, nSize, NULL);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetString(unsigned int nIndex, LPCSTR lpszData, int nSize)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = sqlite3_bind_text(m_pStmt, nIndex, lpszData, strlen(lpszData), NULL);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

HRESULT CStatementImpl::SetDateTime(unsigned int nIndex, int64 nDateTime)
{
    rc_error((nIndex > 0 || nIndex <= m_nParamCount), E_FAIL);
    int rc = SetInt64(nIndex, nDateTime);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}

int CStatementImpl::Commit()
{
    int rc = sqlite3_step(m_pStmt);
    rc_error(rc == SQLITE_DONE, E_FAIL);
    return sqlite3_changes(m_pSqlite3);
}

HRESULT CStatementImpl::Free()
{
    m_pStmt.dispose();
    return S_OK;
}

HRESULT CStatementImpl::Reset()
{
    int rc = sqlite3_reset(m_pStmt);
    rc_error(rc == SQLITE_OK, E_FAIL);
    return S_OK;
}
